﻿package bdz.projects.lavender.doi.ui
{
	import bdz.common.display.DisplayLoader;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import gs.*;
	import gs.easing.*;
	import org.papervision3d.materials.MovieMaterial;
	import flash.utils.*;
	import org.papervision3d.core.proto.DisplayObjectContainer3D;
	import org.papervision3d.materials.BitmapMaterial;
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.objects.primitives.Plane;
	import org.papervision3d.render.BasicRenderEngine;
	import org.papervision3d.scenes.Scene3D;
	import org.papervision3d.view.BasicView;
	import org.papervision3d.cameras.*;
	import org.papervision3d.view.Viewport3D;
	import org.papervision3d.Papervision3D;
	/**
	 * ...
	 * @author ...
	 */
	public class DOI3DView extends BasicView
	{
		
		private var _container:DisplayObject3D;
		private var _dataSource:Array;
		private var _currentStep:Number = 0;
		private var _currentDefinition:XML;
		private var _inited:Boolean = false;
		private var _screenLoader:DisplayLoader;
		private var _currentPlane:Plane;
		private var _prevPlane:Plane;
		private var _currentBitmap:BitmapData;
		private var _rotStart:Number = 90;
		private var _zStart:Number = 1000;
		private var _bcurve:Number = 500;
		private var _switchSpeed:Number = 2;
		private var _maxStep:Number;
		private var _focusArea:Rectangle;
		private var _screenCenter:Point;
		private var _focusPlane:Plane;
		
		function DOI3DView(vwidth:Number = 640, vheight:Number = 480, scaleToStage:Boolean = true, interactive:Boolean = false, cam:String = "Target") {
			//remove pv3d logging
			Papervision3D.PAPERLOGGER.unregisterLogger(Papervision3D.PAPERLOGGER.traceLogger);
			super(vwidth, vheight, scaleToStage, interactive, cam);
			addEventListener(Event.ADDED_TO_STAGE, initializeComponent);
			
		}
		protected function createStepView(xm:XML):void {
			_focusArea = null;
			for each(var ele:XML in xm.element) {
				if (ele.classname.toString() == "FLFocusBox") {
					_focusArea = new Rectangle();
					_focusArea.x = Number(ele.containerx.toString()) + Number(ele.elementx.toString());
					_focusArea.y = Number(ele.containery.toString()) + Number(ele.elementy.toString());
					_focusArea.width = Number(ele.compwidth.toString());
					_focusArea.height = Number(ele.compheight.toString());
				}
			}
			createFocusedArea();
		}
		protected function createPlaneHolder(mc:MovieClip):Plane {
			var mat:MovieMaterial = new MovieMaterial(mc, true, true, true);
			mat.name = "mc";
			mat.doubleSided = true;
			var pl:Plane = new Plane(mat, _currentBitmap.width, _currentBitmap.height, 16, 16);
			pl.rotationY = _rotStart;
			return pl;
		}
		protected function testRotation(evt:MouseEvent):void {
			if (_currentStep < _maxStep-1){
				_currentStep++;
			}else {
				_currentStep = 0;
			}
			_screenLoader.source = _dataSource[_currentStep].swfimage;
		}
		protected function initWithData():void {
			_inited = true;
			_maxStep = _dataSource.length;
			_screenLoader.source = _dataSource[_currentStep].swfimage;
		}
		protected function onScreenLoaded(evt:Event):void {
			_prevPlane = _currentPlane;
			try{
				_currentBitmap.dispose();
			}catch (e:Error) {
				
			}
			_currentBitmap = _screenLoader.bitmap;
			_currentPlane = createPlaneHolder(_screenLoader.content as MovieClip);
			_currentPlane.z = _zStart;
			
			_container.addChild(_currentPlane, "view" + _currentStep);
			bringPlaneToFront(_currentPlane);
			if(_prevPlane){
				bringPlaneToBack(_prevPlane);
			}
		}
		protected function createFocusPlane(bmp:BitmapData):Plane {
			var mat:BitmapMaterial = new BitmapMaterial(bmp, true);
			mat.doubleSided = true;
			var pl:Plane = new Plane(mat, bmp.width, bmp.height, 16, 16);
			return pl;
			
		}
		protected function createFocusedArea() {
			if(_focusArea){
				var nbmp:BitmapData = new BitmapData(_focusArea.width, _focusArea.height, true, 0x00ffffff);	
				nbmp.copyPixels(_currentBitmap, _focusArea, new Point());
				var pl:Plane = createFocusPlane(nbmp);
				pl.z = accurateZ();
				pl.x -= ((_currentBitmap.width / 2) - _focusArea.x)-_focusArea.width/2;
				pl.y = ((_currentBitmap.height / 2) - _focusArea.y) - _focusArea.height / 2;
				_focusPlane = pl;
				_container.addChild(pl);
			}
			setTimeout(showFocusedArea, 1000);
			//showFocusedArea();
	
		}
		protected function showFocusedArea():void {
			TweenMax.to(_currentPlane, _switchSpeed, { z:accurateZ() + 2000, rotationY: -90, ease:Strong.easeInOut } );
			TweenMax.to(_container, _switchSpeed, {  z:0, ease:Strong.easeInOut } );
			TweenMax.to(_focusPlane, _switchSpeed, {  x:0, y:0, z:accurateZ(), ease:Strong.easeInOut } );
		}
		protected function planeUpFront():void {
			createStepView(new XML(_dataSource[_currentStep].definition));
		}
		protected function removePlane(pl:Plane) {
			
			_container.removeChild(pl);
			
		}
		protected function bringPlaneToFront(pl:Plane):void {
			TweenMax.to(pl, _switchSpeed, {bezier:[{x:pl.x, z:pl.z}, {x:pl.x+_bcurve}, {x:pl.x, z:accurateZ()}], rotationY:0,  ease:Strong.easeInOut, onComplete:planeUpFront } );
		}
		protected function bringPlaneToBack(pl:Plane):void {
			TweenMax.to(pl, _switchSpeed, {bezier:[{x:pl.x, z:pl.z}, {x:pl.x-_bcurve}, {x:pl.x, z:_zStart}], rotationY:-_rotStart, ease:Strong.easeInOut, onComplete:removePlane, onCompleteParams:[pl]} );
		}
		protected function initializeComponent(evt:Event):void {
			_screenLoader = new DisplayLoader();
			_screenLoader.addEventListener(Event.COMPLETE, onScreenLoaded);
			_container = new DisplayObject3D("container");
			camera.focus = 10;
			scene.addChild(_container, "container");
			addEventListener(Event.ENTER_FRAME, render);
			if (_dataSource && !_inited) {
				initWithData();
			}
			stage.addEventListener(MouseEvent.CLICK, testRotation);
		}
		
		
		
		protected function render(evt:Event = null):void {
			singleRender();
		}
		protected function accurateZ():Number {
			return (camera.zoom * camera.focus) - Math.abs(camera.z);
		}
		public function set dataProvider(dp:Array):void {
			_dataSource = dp;
			if (!_inited) {
				initWithData();
			}
		}
		public function get dataProvider():Array {
			return _dataSource;
		}
	}
	
}